#include "Main.h"

byte* cplayermgrPtr;
byte* GetMeFunctionPtr;
byte* FindByNameFunctionPtr;
byte* FindPlayerByIdFunctionPtr;
byte* SelectTargetFunctionPtr;
byte* PlayerIterNextFunctionPtr;
byte* InteractFunctionPtr;

void CPlayerMgr::Init()
{
	__try {
		cplayermgrPtr = (byte*)(*(dword*)Mem->GetAddress("CPlayerMgrPtr"));
		GetMeFunctionPtr = Mem->GetAddress("GetMeFunction");
		FindByNameFunctionPtr = Mem->GetAddress("FindByNameFunction");
		FindPlayerByIdFunctionPtr = Mem->GetAddress("FindPlayerByIdFunction");
		SelectTargetFunctionPtr = Mem->GetAddress("SelectTargetFunction");
		PlayerIterNextFunctionPtr = Mem->GetAddress("PlayerIterNextFunction");
		InteractFunctionPtr = Mem->GetAddress("InteractFunction");
	}
	__except(1) { }
}

CPlayer* CPlayerMgr::GetMe()
{
	byte* playerPtr;

	if(!cplayermgrPtr || !GetMeFunctionPtr)
		return NULL;

	_asm {
		MOV ECX,cplayermgrPtr
		CALL GetMeFunctionPtr
		MOV playerPtr,EAX
	}

	return new CPlayer(playerPtr);
}

CPlayer* CPlayerMgr::FindByName(char* name)
{
	byte* playerPtr;

	if(!cplayermgrPtr || !FindByNameFunctionPtr)
		return NULL;

	_asm {
		PUSH name
		MOV ECX,cplayermgrPtr
		CALL FindByNameFunctionPtr
		MOV playerPtr,EAX
	}

	return new CPlayer(playerPtr);
}

CPlayer* CPlayerMgr::FindPlayerById(long id)
{
	byte* playerPtr;

	if(!cplayermgrPtr || !FindPlayerByIdFunctionPtr)
		return NULL;

	_asm {
		PUSH id
		MOV ECX,cplayermgrPtr
		CALL FindPlayerByIdFunctionPtr
		MOV playerPtr,EAX
	}

	return new CPlayer(playerPtr);
}

void CPlayerMgr::SelectTarget(long id)
{
	if(!cplayermgrPtr || !SelectTargetFunctionPtr)
		return;

	_asm {
		PUSH id
		MOV ECX,cplayermgrPtr
		CALL SelectTargetFunctionPtr
	}
}

byte* CPlayerMgr::IterGetFirst()
{
	if(!cplayermgrPtr)
		return NULL;

	__try {
		byte* pListOriginPtr = cplayermgrPtr + 0x60;
		byte* pListPtr = (byte*)(*(dword*)(pListOriginPtr + 4));
		byte* pPlayerList = (byte*)(*(dword*)pListPtr);

		if(pListPtr == pPlayerList)
			return NULL;

		return pPlayerList;
	}
	__except(1) {
		return NULL;
	}
}

byte* CPlayerMgr::IterGetNext(byte* playerList)
{
	byte* playerListPtr;

	if(!cplayermgrPtr || !PlayerIterNextFunctionPtr || !playerList)
		return NULL;

	byte** pArgs = new byte*[2];
	pArgs[0] = cplayermgrPtr + 0x60;
	pArgs[1] = playerList;

	_asm {
		MOV ECX,pArgs
		CALL PlayerIterNextFunctionPtr
	}

	playerListPtr = pArgs[1];

	delete [] pArgs;

	if(playerListPtr == (byte*)(*(dword*)(cplayermgrPtr + 0x64)))
		return NULL;

	return playerListPtr;
}

CPlayer* CPlayerMgr::GetPlayerFromIter(byte* playerList)
{
	if(!playerList)
		return NULL;

	if(!(*(dword*)(playerList + 0x10)))
		return NULL;

	return new CPlayer((byte*)(*(dword*)(playerList + 0x10)));
}

CPlayer* CPlayerMgr::GetClosestPlayerByName(char* name, bool bFullHp)
{
	int iPlayer = 0;

	float fDist = 5000;
	float fTemp = 0;

	CPlayer* player = NULL;
	CPlayer* me = CPlayerMgr::GetMe();
	CPlayer* closest = NULL;

	byte* plIter = IterGetFirst();
	do
	{
		iPlayer++;

		player = GetPlayerFromIter(plIter);
		if(player)
		{
			if(_stricmp(player->GetName(), name) == NULL)
			{
				fTemp = pow(player->GetX() - me->GetX(), 2) + pow(player->GetY() - me->GetY(), 2);
				if(fTemp < fDist && !player->GetIsDead())
				{
					if(bFullHp)
					{
						if(player->GetCurrentHp() == player->GetMaxHp())
						{
							fDist = fTemp;
							delete closest;
							closest = new CPlayer(player->GetBasePtr());
						}
					}
					else
					{
						fDist = fTemp;
						delete closest;
						closest = new CPlayer(player->GetBasePtr());
					}
				}
			}
		}
		delete player;

		plIter = IterGetNext(plIter);
	} while(plIter);

	delete me;

	return closest;
}

void CPlayerMgr::Interact(long id)
{
	if(!cplayermgrPtr || !InteractFunctionPtr)
		return;

	_asm {
		PUSH id
		MOV ECX,cplayermgrPtr
		CALL InteractFunctionPtr
	}
}